package com.example.shader;

import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

public class Sprite {
    public Sprite(Bitmap bmp){     
      mProgram = GLES20.glCreateProgram();
      
      int vertShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
      GLES20.glShaderSource(vertShader, vShaderByteArray);
      GLES20.glCompileShader(vertShader);
      // Get the compilation status.
      final int[] compileStatus = new int[1];
      GLES20.glGetShaderiv(vertShader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

      // If the compilation failed, delete the shader.
      if (compileStatus[0] == 0) {
          Log.e(TAG,
                  "Error compiling shader: "
                          + GLES20.glGetShaderInfoLog(vertShader));
          GLES20.glDeleteShader(vertShader);
          vertShader = 0;
      }
      checkGLError("vertShader");
      
      int fragShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
//      GLES20.glShaderSource(fragShader, fShaderByteArray);
      GLES20.glShaderSource(fragShader, filterFSH);   
      GLES20.glCompileShader(fragShader);
      // Get the compilation status.
      GLES20.glGetShaderiv(fragShader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

      // If the compilation failed, delete the shader.
      if (compileStatus[0] == 0) {
          Log.e(TAG,
                  "Error compiling shader: "
                          + GLES20.glGetShaderInfoLog(fragShader));
          GLES20.glDeleteShader(fragShader);
          fragShader = 0;
      }
      checkGLError("fragShader");
      
      //为着色程序添加顶点与片元着色程序
      GLES20.glAttachShader(mProgram, vertShader);
      checkGLError("vertShader 222");
      GLES20.glAttachShader(mProgram, fragShader);       
      checkGLError("fragShader 222");  
      
      GLES20.glLinkProgram(mProgram);
      checkGLError("glLinkProgram 222");
      GLES20.glDeleteShader(vertShader);
      GLES20.glDeleteShader(fragShader);      
      checkGLError("glDeleteShader"); 
      GLES20.glUseProgram(mProgram);
      mVertexLoc = GLES20.glGetAttribLocation(mProgram, "aPosition");
      checkGLError("glLinkProgram 1111"); 
     
      mTexCoorLoc = GLES20.glGetAttribLocation(mProgram, "aTexCoor");
      checkGLError("glLinkProgram 3333"); 
      
      mTexLoc = GLES20.glGetUniformLocation(mProgram, "tex");
      GLES20.glUniform1i(mTexLoc, 10);
      checkGLError("glLinkProgram 333");
      
      mTexSizeLoc = GLES20.glGetUniformLocation(mProgram, "texSize");
      GLES20.glUniform2f(mTexSizeLoc, bmp.getWidth(), bmp.getHeight());
      checkGLError("glLinkProgram 444");
      
      GLES20.glEnableVertexAttribArray(mVertexLoc);
      checkGLError("glLinkProgram 2222"); 
      GLES20.glEnableVertexAttribArray(mTexCoorLoc);
      checkGLError("glLinkProgram 4444");
      float[] quadVertexCoor = {  
              -1.0f, 1.0f, 0.0f, 1.0f, 
              -1.0f, -1.0f, 0.0f, 1.0f,                                                                    
              1.0f, -1.0f, 0.0f, 1.0f, 
              
              -1.0f, 1.0f, 0.0f, 1.0f, 
              1.0f, -1.0f, 0.0f, 1.0f,                                                                    
              1.0f, 1.0f, 0.0f, 1.0f,
      };
        mQuadVerticesCoor = ByteBuffer
        .allocateDirect(quadVertexCoor.length * 4)
        .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mQuadVerticesCoor.put(quadVertexCoor);
        mQuadVerticesCoor.position(0); 
        
        float[] texCoor = {  
                0.0f, 0.0f,
                0.0f, 1.0f,                                                           
                1.0f, 1.0f,
                
                0.0f, 0.0f,
                1.0f, 1.0f,                                            
                1.0f, 0.0f,
        };
        mTexCoor = ByteBuffer
          .allocateDirect(texCoor.length * 4)
          .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTexCoor.put(texCoor);
        mTexCoor.position(0); 
        
        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);
        mTexId = textures[0];
        GLES20.glActiveTexture(GLES20.GL_TEXTURE10);        
        checkGLError("checkGLError 61  mTexId=" + mTexId);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexId);      
        checkGLError("checkGLError 62  mTexId=" + mTexId);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        checkGLError("checkGLError 6  mTexId=" + mTexId);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
        bmp.recycle();
    }
    
    public void draw(){
        GLES20.glUseProgram(mProgram);
        GLES20.glVertexAttribPointer(mVertexLoc, 4, GLES20.GL_FLOAT,
                false, 0, mQuadVerticesCoor);  
        checkGLError("checkGLError 1");
        GLES20.glVertexAttribPointer(mTexCoorLoc, 2, GLES20.GL_FLOAT,
                false, 0, mTexCoor);    
        checkGLError("checkGLError 2");
        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexId);
    
        checkGLError("checkGLError 3");
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        checkGLError("checkGLError 4");
    }
    
    public static void checkGLError(String label) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, label + ": glError " + error);
            throw new RuntimeException(label + ": glError 0x" + Integer.toHexString(error));
        }
    }
    
    private static final String TAG = Triangle.class.getSimpleName();
    private int mProgram;
    private FloatBuffer mQuadVerticesCoor;  
    private FloatBuffer mTexCoor;
    private int mVertexLoc;
    private int mTexCoorLoc;
    private int mTexLoc;
    private int mTexId;
    private float mTexWidth;
    private float mTexHeight;
    private int mTexSizeLoc;
    private final static String vShaderByteArray = new String("attribute vec4 aPosition;"+
                                                            "attribute vec2 aTexCoor;"+
                                                            "varying vec2 vTexCoord;"+
                                                            "void main() {"+
                                                            "vTexCoord = aTexCoor;"+
                                                            "gl_Position = aPosition;"+
                                                            "}");
    private final static String fShaderByteArray = new String("precision mediump float;"+
                                                              "varying vec2 vTexCoord;"+
                                                              "uniform sampler2D tex;"+
                                                              "void main() {"+                                                                   
                                                              "gl_FragColor = texture2D(tex, vTexCoord);"+
                                                              "}");
    // 浮雕
    private final static String filterFSH = "precision mediump float;" +
                                            "varying vec2 vTexCoord;" +
                                            "uniform sampler2D tex;" +
                                            "uniform vec2 texSize;" +
                                            "void main() {" +
                                            "vec2 leftTopCoord = vec2(vTexCoord.x - 1.0/texSize.x, vTexCoord.y - 1.0/texSize.y);" +
                                            "float h = 0.3*deltaColor.x + 0.6*deltaColor.y + 0.1*deltaColor.z;" +
                                            "gl_FragColor = vec4(h, h, h, 0.0) + vec4(0.5,0.5,0.5,1.0);" +
                                            "}";
}
